/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package utilities;

import bdl.UtilityBean;
import entities.Match;
import entities.Prediction;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import javax.swing.table.DefaultTableModel;
import utilities.entities.RatedColumn;
import utilities.entities.SelectionList;
import utilities.entities.Result;
import utilities.entities.Selection;

/**
 *
 * @author olawale
 */
public class Rating {

//    static ArrayList<Result> pResults = Store.getAll();
    private static SimpleDateFormat sdf = new SimpleDateFormat("EEE, dd MMM yyyy");
    

    public Rating(Date date){
        predictions = UtilityBean.getRatedPredictions(date, date);
    }

    public Rating(Date sdate, Date edate){
        predictions = UtilityBean.getRatedPredictions(sdate, edate);
    }

    private List<Prediction> predictions;
    private DefaultTableModel dtm;
    private String message;
    private int rowCount;


    public void rate(SelectionList result){
        if(predictions == null || predictions.size() == 0){
            message = "No prediction to rate";
            return;
        }
        ArrayList<String> colNames = new ArrayList();
        colNames.add("Match Played Date.");
        colNames.add("Match Fixture Number.");
        colNames.add("Prediction Reference Number.");
        for(Selection sel : result.getSelected()){
            colNames.add(sel.getColumn().getColumnName()+"..");
        }
        colNames.add("Search Date Range.");
        colNames.add("Prediction Performance Score.");
        colNames.add("Rating Performance Feature.");
        colNames.add("Rating Performance Feature Count.");
        if(!result.isOnly()){
            for(Selection sel : result.getSelections()){
                if(sel.isSelected()) continue;
                colNames.add(sel.getColumn().getColumnName() + "-");
                colNames.add(sel.getColumn().getColumnName() + " Rating Count.");
            }
        }

        dtm = new DefaultTableModel(new Object [][] {}, colNames.toArray()){
            @Override
            public boolean isCellEditable(int row, int column) {
                return false;
            }
        };


//        dtm.setRowCount(predictions.size());
        dtm.setRowCount(1);
        rowCount = 0;
        System.out.println("---------- " + predictions.size());
        for(int i = 0; i < predictions.size(); i++){
            Prediction pred = predictions.get(i);
            DefaultTableModel tm = getData(pred);
            if(tm == null) continue;
            ++rowCount;
            int c = 0;
            for(int j = 0; j < dtm.getColumnCount(); j++){
                if(colNames.get(j).contains(".") || colNames.get(j).isEmpty()){
                    if(colNames.get(j).equals("Match Played Date.")){
                        dtm.setValueAt(sdf.format(pred.getMatch().getMatchDate()), i, j);
                    }
                    if(colNames.get(j).equals("Match Fixture Number.")){
                        dtm.setValueAt(pred.getMatch().getFixture(), i, j);
                    }
                    if(colNames.get(j).equals("Prediction Reference Number.")){
                        dtm.setValueAt(pred.getId(), i, j);
                    }
                    if(colNames.get(j).equals("Search Date Range.")){
                        dtm.setValueAt(tm.getValueAt(0, 0), i, j);
                    }
                    if(colNames.get(j).equals("Prediction Performance Score.")){
                        dtm.setValueAt(pred.getRating1() + "pt", i, j);
                    }
                    if(colNames.get(j).equals("Rating Performance Feature.")){
                        int r = pred.getRating1();
                        String rpf = (pred.getRating1() == 1) ? (r + " + s") : (r + " - 1f");
                        dtm.setValueAt(rpf, i, j);
                    }
                    if(colNames.get(j).equals("Rating Performance Feature Count.")){
                        dtm.setValueAt("", i, j);
                    }
                    continue;
                }
                if(c == (tm.getColumnCount() - 1)) break;

                dtm.setValueAt(tm.getValueAt(0, ++c), i, j);

            }
        }

        if(rowCount == 0){
            return;
        }
        
        for(int col = 0; col < dtm.getColumnCount(); col++){
            String cname = colNames.get(col);
            if(cname.contains("-")){
                rateFeature(col);
            }else if(cname.contains("Rating Performance Feature Count.")){
                ratePerformance(col);
            }else if(cname.contains("..")){
                
            }
        }
    }

    public void extract(SelectionList result){
        if(predictions == null || predictions.size() == 0){
            message = "No prediction to rate";
            return;
        }
        ArrayList<String> colNames = new ArrayList();
        for(Selection sel : result.getSelections()){
            colNames.add(sel.getColumn().getColumnName());
        }

        dtm = new DefaultTableModel(new Object [][] {}, colNames.toArray()){
            @Override
            public boolean isCellEditable(int row, int column) {
                return false;
            }
        };


        dtm.setRowCount(predictions.size());
        rowCount = 0;
        for(int i = 0; i < predictions.size(); i++){
            Prediction pred = predictions.get(i);
            DefaultTableModel tm = getData(pred);
            if(tm == null) continue;
            int c = 0;
            ++rowCount;
            for(int j = 0; j < tm.getColumnCount(); j++){
                if(c == (tm.getColumnCount() - 1)) break;
                dtm.setValueAt(tm.getValueAt(0, ++c), i, j);
            }
        }

        if(rowCount == 0) return;


        ArrayList<Integer> toRemove = new ArrayList();
        ArrayList<Selection> selecteds = result.getSelected();
        for(int row = 0; row < dtm.getRowCount(); row++){
            for(int col = 0; col < dtm.getColumnCount(); col++){
                String cname = colNames.get(col);
                Selection ss = new Selection(new RatedColumn(cname, col), true, null);
                if(selecteds.contains(ss)){
                    int indx = result.getSelected().indexOf(ss);
                    if(!compare(selecteds.get(indx).getCompareValue(), dtm.getValueAt(row, col)))
                        toRemove.add(row);
                }
            }
        }

        int count = 0;
        for(Integer rev : toRemove){
            dtm.removeRow(rev - count);
            ++count;
        }
    }

    public void autosearch(int [] range, int msf){
        ArrayList sels = SelectionList.getDefault(false);
        rate(new SelectionList(sels, false));
        if(!isValid()){
            message = "";
            return;
        }
        ArrayList<Integer> rows = new ArrayList();
        ArrayList<String> cols = new ArrayList();
        if(range != null){
            outer:
            for(int row = 0; row < dtm.getRowCount(); row++){
                for(int col = 0; col < dtm.getColumnCount(); col++){
                    String cname = dtm.getColumnName(col);
                    if(range != null && cname.contains("108")){
                        int tot = Utility.parseInt(dtm.getValueAt(row, col).toString());
                        if(tot > -1 && tot >= range[0] && tot <= range[1]){
                            rows.add(row);
                        }
                        continue outer;
                    }
                }
            }
        }else{
            for(int row = 0; row < dtm.getRowCount(); row++){
                rows.add(row);
            }
        }

        outer:
        for(int col = 0; col < dtm.getColumnCount(); col++){
            String cname = dtm.getColumnName(col);
            if(cname.contains("Rating Count.")){
                for(int row = 0; row < dtm.getRowCount(); row++){
                    int rate = Utility.parseInt(dtm.getValueAt(row, col).toString());
                    if(rate >= msf){
                        String next = dtm.getColumnName(col + 1);
                        cols.add(next);
                        continue outer;
                    }
                }
            }
        }

        ArrayList<Selection> selections = SelectionList.getDefault(true);
        ArrayList<Selection> toRemove = new ArrayList();
        
        for(int i = 0; i < selections.size(); i++ ){
            Selection sel = selections.get(i);
            String cn = sel.getColumn().getColumnName();
            System.out.println(cn);
            if(!cols.contains(sel.getColumn().getColumnName() + "-")){
                toRemove.add(sel);
            }
        }

        for(Selection re : toRemove){
            try{
                System.out.println(selections.remove(re));
            }catch(Exception ex){
                System.out.println("no. " + re + " " + ex);
            }
        }

        rate(new SelectionList(selections, true));
        
    }

    public void probabiltyRate(){
        ArrayList<Selection> selections = SelectionList.getDefault(false);
        rate(new SelectionList(selections, false));
    }

    public boolean isValid(){
//        try {
//            Thread.sleep(3000);
//        } catch (Exception ex) {
//            System.err.println("thread exception " + ex.toString());
//        }
        if(dtm.getColumnCount() > 0 && dtm.getRowCount() > 0 && rowCount > 0)
            return true;
        else{
            message = "no data generated";
            return false;
        }
    }
    
    public DefaultTableModel getTableModel(){
        return dtm;
    }
    
    public String getMessage(){
        return message;
    }

    private boolean compare(Object cValue, Object aValue){
        if(aValue.toString().isEmpty())
            return false;

        String type = aValue.getClass().getName();
        if(type.equals("javax.swing.table.DefaultTableModel")){
            DefaultTableModel adtm = (DefaultTableModel) aValue;
            if(compareType(cValue, aValue)){
                DefaultTableModel cdtm = (DefaultTableModel) cValue;
                if(!adtm.getValueAt(1, 0).toString().equals(cdtm.getValueAt(1, 0).toString()))
                    return false;
                else if(!adtm.getValueAt(1, 1).toString().equals(cdtm.getValueAt(1, 1).toString()))
                    return false;
                else
                    return true;
            }else if(cValue.getClass().isArray()){
                String[] cval = (String[]) cValue;
                if(!adtm.getValueAt(1, 0).toString().equals(cval[0]))
                    return false;
                else if(!adtm.getValueAt(1, 1).toString().equals(cval[1]))
                    return false;
                else
                    return true;
            }

        }else if(type.equals("java.lang.Long")){
            Long aval = Long.parseLong(aValue.toString());
            if(compareType(cValue, aValue)){
                Long cval = Long.parseLong(cValue.toString());
                if(aval != cval)
                    return false;
                else
                    return true;
            }else if(cValue.getClass().isArray()){
                String [] arr = (String[]) cValue;
                Long cval = Long.parseLong(arr[0]);
                if(aval != cval)
                    return false;
                else
                    return true;
            }
        }else if(type.equals("java.lang.Integer")){
            Integer aval = Integer.parseInt(aValue.toString());
            if(compareType(cValue, aValue)){
                Integer cval = Integer.parseInt(cValue.toString());
                if(aval != cval)
                    return false;
                else
                    return true;
            }else if(cValue.getClass().isArray()){
                String [] arr = (String[]) cValue;
                Integer cval = Integer.parseInt(arr[0]);
                if(aval != cval)
                    return false;
                else
                    return true;
            }
        }else if(type.equals("entities.Match")){
            Match amatch = (Match) aValue;
            if(compareType(cValue, aValue)){
                if(amatch.toString().equals(cValue.toString()))
                    return true;
                else
                    return false;
            }else if(cValue.getClass().isArray()){
                String [] cval = (String[]) cValue;
                if(amatch.toString().equals(cval[0]))
                    return false;
                else
                    return true;
            }
        }else if(type.equals("java.lang.String")){
            if(compareType(aValue, cValue)){
                if(aValue.toString().equals(cValue.toString()))
                    return true;
                else
                    return false;
            }else if(cValue.getClass().isArray()){
                String [] cval = (String[]) cValue;
                if(aValue.toString().equals(cval[0].toString()))
                    return true;
                else
                    return false;
            }
        }else if(type.equals("[Ljava.lang.Object;")){
            Object [] aval = (Object[]) aValue;
            if(compareType(aValue, cValue)){
                Object [] cval = (Object[]) cValue;
                int c = (aval.length < cval.length) ? aval.length : cval.length;
                for(int i = 0; i < c; i++){
                    if(!aval[i].equals(cval[i]))
                        return false;
                }
                return true;
            }else if(cValue.getClass().isArray()){
                String [] cval = (String[]) cValue;
                for(int i = 0; i < aval.length; i+=2){
                    if(i == (aval.length - 1)) break;
                    if(!cval[i].equals(aval[i].toString() + aval[i+1].toString()))
                        return false;
                }
                return true;
            }else{
                String [] cval = ((String) cValue).split(",");
                for(int i = 0; i < aval.length; i++){
                    for(int j = 0; j < cval.length; j++){
                        if(cval[j].equals(aval[i]))
                        return true;
                    }
                }
                return false;
            }
        }else if(type.equals("java.util.Date")){
            Date aval = (Date) aValue;
            if(compareType(aValue, cValue)){
                Date cval = (Date) cValue;
                Calendar acal = Calendar.getInstance();
                acal.setTime(aval);
                Calendar ccal = Calendar.getInstance();
                ccal.setTime(cval);
                boolean c1 = acal.get(Calendar.YEAR) == ccal.get(Calendar.YEAR);
                boolean c2 = acal.get(Calendar.MONTH) == ccal.get(Calendar.MONTH);
                boolean c3 = acal.get(Calendar.DATE) == ccal.get(Calendar.DATE);
                return (c1 && c2 && c3);
            }else{
                String[] cval = ((String) cValue).split("/");//  18/09/2009
                int d = Integer.parseInt(cval[0]);
                int m = Integer.parseInt(cval[1]) - 1;
                int y = Integer.parseInt(cval[2]);
                Calendar cal = Calendar.getInstance();
                cal.setTime(aval);
                if(d == cal.get(Calendar.DATE) && m == cal.get(Calendar.MONTH) && y == cal.get(Calendar.YEAR))
                    return true;
                else
                    return false;
            }
        }
        return false;
    }

    private <T, V> boolean compareType(T t, V v){
        return v.getClass().getName().equals(t.getClass().getName());
    }

    private static DefaultTableModel getData(Prediction pred){
        Result result = Store.retrieve(pred.getFileName());
        if(result == null) return null;
        DefaultTableModel dtm = new DefaultTableModel();
        dtm.setRowCount(1);
        ResultFixture rf = new ResultFixture(result, dtm, 0);
        rf.fillData();
        return rf.getData();
    }



    private void rateFeature(int col){
        ArrayList colData = new ArrayList();
        boolean empty = true;
        for(int row = 0; row < dtm.getRowCount(); row++){
            Object value = dtm.getValueAt(row, col);
            if(value != null){
                empty = false;
            }
            if(value != null && value.getClass().getName().contains("String")){
                if(((String)value).isEmpty()) empty = true;
            }
            colData.add(dtm.getValueAt(row, col));
        }

        if(empty){
            col = col + 1;
            for(int row = 0; row < dtm.getRowCount(); row++){
                dtm.setValueAt(" N/A ", row, col);
            }
        }else{
            int rate = 0;
            Object prev = dtm.getValueAt(0, col);
            for(int row = 0; row < dtm.getRowCount(); row++){
                Object pres = dtm.getValueAt(row, col);
                if(compare(prev, pres)){
                    ++rate;
                }else{
                    rate = 0;
                }
                dtm.setValueAt(rate, row, (col+1));
                prev = pres;
            }
        }
    }

    private void ratePerformance(int col){
        int scount = 0;
        int fcount = 0;
        int prev = -1;
        for(int row = 0; row < dtm.getRowCount(); row++){
            String r = (String) dtm.getValueAt(row, (col-1));
            int rate = Integer.parseInt(r.split(" ")[0]);
            String perf = "";
            if(rate == prev){
                fcount = 0;
                ++scount;
                perf = scount + " + s";
            }else{
                scount = 0;
                ++fcount;
                perf = fcount + " + f";
            }
            dtm.setValueAt(perf, row, col);
            prev = rate;
        }
    }
    
}
